/*
 *Copyright (c) [2019-2020]  C2comm, Inc.  All rights reserved.
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; If not, see <https://www.gnu.org/licenses/>
 */
/*
 *Vendor: C2comm
 *Version: 1.0
 *Filename: CMStable.v
 *Target Device: Altera
 *Author : 刘晓骏
*/

module CMStable(
    input  wire        SYS2CORE_clk,
    input  wire        SYS2CORE_rst_n,
    
    input  wire [19:0] GA2STA_local_clk,
    
    input  wire        GA2STA_guard_state_cs,

    output wire        STA2GA_guard_pcf_ready,
    
    input  wire [ 7:0] GA2STA_guard_stable_cycle_ctr,
    
    input  wire [67:0] GA2STA_guard_conf,    
    input  wire [ 2:0] GA2STA_guard_clique_in, 
    
    output reg         STA2CS_cmd_valid,
    output reg  [5:0]  STA2CS_cmd_next_top_state,
    output wire [7:0]  STA2CS_cmd_bottom_state
);
/*//////////////////////////////////////////////////////////
                    中间变量声明区域
*///////////////////////////////////////////////////////////
//本模块中所有中间变量(wire/reg/parameter)在此集中声明 
reg [7:0] next_sta_state;
reg [7:0] curr_sta_state;

localparam CM_INTEGRATE  = 6'b000001,
           CM_UNSYNC     = 6'b000010,
           CM_CA_ENABLED = 6'b000100,
           CM_WAIT_4_IN  = 6'b001000,
           CM_SYNC       = 6'b010000,
           CM_STABLE     = 6'b100000;
           
localparam INIT_S     = 8'b00000001,
           MATCH_S    = 8'b00000010,
           COMPLETE_S = 8'b00000100,
           C0_S       = 8'b00001000,
           C1_S       = 8'b00010000,
           C2_S       = 8'b00100000,
           C3_S       = 8'b01000000,
           C4_S       = 8'b10000000;
/*//////////////////////////////////////////////////////////
                    状态机跳转处理
*///////////////////////////////////////////////////////////
assign STA2CS_cmd_bottom_state = next_sta_state;

assign STA2GA_guard_pcf_ready = (next_sta_state == MATCH_S);


//根据当前状态和输入条件来决定下一跳的状态
//采用三段式实现状态机，使得编写逻辑时可以方便使用组合逻辑部分作为条件以规避时序逻辑带来的1个周期的延时
always @* begin
    case(curr_sta_state)
        INIT_S: begin
            if(GA2STA_guard_state_cs == 1'b1)
                next_sta_state = MATCH_S;
            else
                next_sta_state = INIT_S;
        end
        
        MATCH_S: begin//modify by lxj 20200427
            if((GA2STA_local_clk == GA2STA_guard_conf[39:20]) && 
               (GA2STA_guard_clique_in[2] == 1'd1))
                next_sta_state = C0_S;
            else if((GA2STA_local_clk == GA2STA_guard_conf[59:40]) && 
                    (GA2STA_guard_clique_in[0] == 1'd1) && 
                    (GA2STA_guard_stable_cycle_ctr < GA2STA_guard_conf[67:60]))
                next_sta_state = C1_S;
            else if((GA2STA_local_clk == GA2STA_guard_conf[59:40]) && 
                    (GA2STA_guard_clique_in[0] == 1'd1) && 
                    (GA2STA_guard_stable_cycle_ctr >= GA2STA_guard_conf[67:60]))
                next_sta_state = C2_S;
            else if((GA2STA_local_clk == GA2STA_guard_conf[59:40]) && 
                    (GA2STA_guard_clique_in[1] == 1'd1))
                next_sta_state = C3_S;
            else if(GA2STA_local_clk == GA2STA_guard_conf[19:0])
                next_sta_state = C4_S;
            else
                next_sta_state = MATCH_S;
        end
        
        C0_S: begin
            next_sta_state = COMPLETE_S;
        end
        
        C1_S: begin
            next_sta_state = COMPLETE_S;
        end
        
        C2_S: begin
            next_sta_state = COMPLETE_S;
        end
        
        C3_S: begin
            next_sta_state = COMPLETE_S;
        end
        
        C4_S: begin
            next_sta_state = COMPLETE_S;
        end
        
        COMPLETE_S: begin
            next_sta_state = INIT_S;
        end
        
        default: next_sta_state = INIT_S;
    endcase
end

//时序逻辑用于缓存当前状态
always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(SYS2CORE_rst_n == 1'b0) begin
        curr_sta_state <= INIT_S;
    end
    else begin
        curr_sta_state <= next_sta_state;
    end
end

//在该时序逻辑部分实现各状态的执行动作
always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(SYS2CORE_rst_n == 1'b0) begin
        STA2CS_cmd_valid <= 1'b0;
        STA2CS_cmd_next_top_state <= 6'b0;
    end
    else begin
        case(curr_sta_state)
            INIT_S: begin
                STA2CS_cmd_valid <= 1'b0;
                STA2CS_cmd_next_top_state <= 6'b0;
            end
            
            MATCH_S:begin
                STA2CS_cmd_valid <= 1'b0;
                STA2CS_cmd_next_top_state <= 6'b0;
            end
            
            C0_S:begin
                STA2CS_cmd_valid <= 1'b1;
                STA2CS_cmd_next_top_state <= CM_INTEGRATE;
            end
            
            C1_S:begin
                STA2CS_cmd_valid <= 1'b1;
                STA2CS_cmd_next_top_state <= CM_STABLE;
            end
            
            C2_S:begin
                STA2CS_cmd_valid <= 1'b1;
                STA2CS_cmd_next_top_state <= CM_INTEGRATE;
            end
            
            C3_S:begin
                STA2CS_cmd_valid <= 1'b1;
                STA2CS_cmd_next_top_state <= CM_STABLE;
            end
            
            C4_S:begin
                STA2CS_cmd_valid <= 1'b1;
                STA2CS_cmd_next_top_state <= CM_STABLE;
            end
            
            COMPLETE_S:begin
                STA2CS_cmd_valid <= 1'b0;
                STA2CS_cmd_next_top_state <= 6'b0;
            end
            
            default: begin
                STA2CS_cmd_valid <= 1'b0;
                STA2CS_cmd_next_top_state <= 6'b0;
            end
        endcase
    end
end
/*//////////////////////////////////////////////////////////
                   IP调用区域
*///////////////////////////////////////////////////////////
//本模块调用的所有IP在该区域实例化
//例如fifo/ram/grant之类的IP....   
endmodule
/*
CMStable CMStable_inst(
    .SYS2CORE_clk(),
    .SYS2CORE_rst_n(),

    .GA2STA_local_clk(),

    .GA2STA_guard_state_cs(),

    .STA2GA_guard_pcf_ready(),

    .GA2STA_guard_stable_cycle_ctr(),

    .GA2STA_guard_conf(),    
    .GA2STA_guard_clique_in(), 

    .STA2CS_cmd_valid(),
    .STA2CS_cmd_next_top_state(),
    .STA2CS_cmd_bottom_state()
);
*/